<template>
  <svg width="100%" :height="svg.height" ref="svg">
    <g
      ref="warpper"
      :transform="
        'translate(' + warperTranslate.x + ',' + warperTranslate.y + ')'
      "
    >
      <g class="links">
        <path
          :d="getTreeLink1(link)"
          v-for="(link, index) in links"
          :key="'link' + index"
          fill="none"
          :class="getClass(link)"
          stroke="#555"
          stroke-width="1.5"
        />
      </g>
      <g class="nodes">
        <g
          class="node"
          v-for="(item, index) in nodes"
          :key="'wdsTree' + index"
          :transform="'translate(' + item.y + ',' + item.x + ')'"
        >
          <foreignObject
            :width="dx"
            :height="dy"
            :transform="'translate(' + (0 - dx / 2) + ',' + (0 - dy / 2) + ')'"
          >
            <slot name="node" :nodeData="item" :index="index"></slot>
          </foreignObject>
        </g>
      </g>
    </g>
  </svg>
</template>
<script>
import * as d3 from 'd3';
export default {
  name: 'RjWDSTree',
  props: {
    wdsData: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      wdsTree: null,
      svg: {
        height: 0,
      },
      config: {
        horizontal: true,
        elbowRadius: 10, //连接线圆角
        elbowfar: 150, //连接线未分叉部分
      },
      warperTranslate: {
        x: 0,
        y: 0,
      },
      space: {
        x: 100,
        y: -50,
      },
      dx: 340,
      dy: 120,
      //tree: d3.tree().nodeSize([this.dx, this.dy]),
      treeData: {},
      nodes: [],
      links: [],
    };
  },
  watch: {
    wdsData: {
      handler(n) {
        this.init();
      },
      deep: true,
    },
  },
  computed: {
    cpeTotal() {
      return this.wdsData?.children?.length || 0;
    },
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      let treeData = d3.hierarchy(this.wdsData);
      this.treeData = this.initTree(treeData);
      let x0 = Infinity;
      let x1 = -x0;
      this.treeData.each((d) => {
        if (d.x > x1) x1 = d.x;
        if (d.x < x0) x0 = d.x;
      });
      this.nodes = this.treeData.descendants().reverse();
      this.links = this.treeData.links();

      this.$nextTick(() => {
        const warpBbox = this.$refs['warpper'].getBBox();
        const svgBbox = this.$refs['svg'].getBoundingClientRect();
        console.log('整体宽高', 'warp', warpBbox, 'svg', svgBbox);
        this.svg.height = warpBbox.height + 40;
        this.warperTranslate.x =
          svgBbox.width / 2 - warpBbox.width / 2 + this.dx / 2;
        this.warperTranslate.y = this.svg.height / 2;
      });
    },
    initTree(treeData) {
      return d3
        .tree()
        .separation(function (a, b) {
          //console.log("间隔访问",a,b)
          return a.parent == treeData && b.parent == treeData ? 2 : 1;
          //return a.parent == b.parent ? 1 : 2
        })
        .nodeSize([this.dy + this.space.y, this.dx + this.space.x])(treeData);
    },
    getTreeLink(link) {
      return d3
        .linkHorizontal()
        .x((d) => d.y)
        .y((d) => d.x)(link);
    },
    getTreeLink1(d) {
      console.log(d);
      if (this.config.horizontal) {
        //return "M" + d.source.y + "," + d.source.x + "H" +(d.source.y+30)+ "V" + d.target.x + "H" + d.target.y;
        let radiusStart =
          d.target.x > d.source.x
            ? d.target.x - this.config.elbowRadius
            : d.target.x < d.source.x
            ? d.target.x + this.config.elbowRadius
            : d.target.x;
        let radiusEndx =
          d.target.x > d.source.x
            ? d.source.x + this.config.elbowRadius
            : d.target.x < d.source.x
            ? d.source.x - this.config.elbowRadius
            : d.target.x;
        return `
        M${d.source.y},${d.source.x}
        H${d.source.y + this.config.elbowfar - this.config.elbowRadius}
        Q${d.source.y + this.config.elbowfar} ${d.source.x},${
          d.source.y + this.config.elbowfar
        } ${radiusEndx} 
        V${radiusStart}
        Q${d.source.y + this.config.elbowfar + ' ' + d.target.x},${
          d.source.y +
          this.config.elbowfar +
          this.config.elbowRadius +
          ' ' +
          d.target.x
        }
        H${d.target.y}`;
      } else {
        //return "M" + d.source.x + "," + d.source.y + "V" + (d.source.y+30) + "H" + d.target.x + "V" + d.target.y;
        //return `M${d.source.x},${d.source.y}V${d.source.y+30}H${d.target.x-elbowRadius}Q${(d.target.x-elbowRadius)+" "+d.source.y+30},${d.target.x+" "+(d.source.y+30+elbowRadius)}V${d.target.y}`
        let radiusStart =
          d.target.x > d.source.x
            ? d.target.x - this.config.elbowRadius
            : d.target.x < d.source.x
            ? d.target.x + this.config.elbowRadius
            : d.target.x;
        let radiusEndx =
          d.target.x > d.source.x
            ? d.source.x + this.config.elbowfar
            : d.target.x < d.source.x
            ? d.source.x - this.config.elbowfar
            : d.target.x;
        return `
        M${d.source.x},${d.source.y}
        Q${d.source.x} ${d.source.y + this.config.elbowfar},${radiusEndx} ${
          d.source.y + this.config.elbowfar
        }
        H${radiusStart}
        Q${d.target.x + ' ' + (d.source.y + this.config.elbowfar)},${
          d.target.x +
          ' ' +
          (d.source.y + this.config.elbowfar + this.config.elbowRadius)
        }
        V${d.target.y}
        `;
      }
    },
    getClass(link) {
      return link.target.data.class.join(' ');
    },
  },
};
</script>
